#ifndef __TROPHY_LOGO_EXECUTOR_NO_WND_H__
#define __TROPHY_LOGO_EXECUTOR_NO_WND_H__

#include "logolib/iexec.h"
#include <stdlib.h>
#include "Stroke.h"

#define DEFAULT_CANVAS_WIDTH     200
#define DEFAULT_CANVAS_HEIGHT    200
#define DEFAULT_PEN_COLOR        RGB(0,0,0)
#define DEFAULT_CANVAS_COLOR     RGB(255,255,255)
#define DEFAULT_DIRECTION        0
#define DEFAULT_SHOW             true
#define DEFAULT_WRAP             true
#define DEFAULT_PEN_WIDTH        1
#define DEFAULT_PEN_DOWN         true
#define DEFAULT_FONT_SIZE        20

#define MAX_TRANVAS              120
   // xcrosses + ycrosses + p0 +p1
#define MAX_STROKE_ENDS          MAX_TRANVAS*2 + 2

class CLogoExecutorNoWnd : public i_exec_t
{
protected:
   // Protected constructor. This class must be derived.
   //  Typically add the implementatiion for 
   //     virtual char* inputwindow (char* str) = 0;
   //     virtual void message (char* str) = 0;
   //     virtual void debug_info (char* str) = 0;
   //     virtual void error_info (char* str) = 0;
   CLogoExecutorNoWnd();
public:
   virtual ~CLogoExecutorNoWnd();
   void SetCanvas(ICanvas* pCanvas);
   // Draw all the strokes overlapping pRect, if pRect is NULL,
   //  draw all the stroke in the list.
   void DrawAllStrokes(RECT* pRect);

public:
   UINT        m_uCanvasWidth;
   UINT        m_uCanvasHeight;
   UINT        m_uFontSize;
   COLORREF    m_clrCanvas;
   COLORREF    m_clrPen;
   UINT        m_uPenWidth;
   POINT       m_ptCurrent;
   double      m_direction;
   bool        m_bShowTurtle;
   bool        m_bWrap;
   bool        m_bPenDown;
   CStroke*    m_pStrokeHead;
   CStroke*    m_pStrokeTail;
   ICanvas*    m_pCanvas;

// i_exec_t interface
public:
   virtual void canvassize (double x, double y);
   virtual void reset (void);
   virtual void clear (void);
   virtual void hide (void);
   virtual void canvascolor (double r, double g, double b);
   virtual void pencolor (double r, double g, double b);
   virtual void penwidth (double w);
   virtual void go (double x, double y);
   virtual void direction (double d);
   virtual void turnright (double d);
   virtual void turnleft (double d);
   virtual void forward (double d);
   virtual void backward (double d);
   virtual void fontsize (double n);
   virtual void print (char* str);
   virtual void penup (void);
   virtual void pendown (void);
   virtual void center (void);
   virtual void gox (double d);
   virtual void goy (double d);
   virtual void wrapon (void);
   virtual void wrapoff (void);
   virtual void show (void);
   /* the returned string shall NOT be freed by the caller. */
   virtual char* inputwindow (char* str) {return NULL;};
   virtual void message (char* str) {};
   virtual void debug_info (char* str) {};
   virtual void error_info (char* str) {};
   virtual void done(void) {};
   virtual void debug_cmd_ack(int lineno) {};

protected:
   void RemoveAllStrokes();
   void AddToStrokeList(CStroke* pStk);
   void LineTo (int x, int y);
   void DistanceToDelta (double distance, int* dx, int* dy);
   void AddLineStroke(POINT* pt0, POINT* pt1);
   void AddYCrossesToStrokeEnds(int nCount, POINT* p0, POINT* p1);
   void AddXCrossesToStrokeEnds(int nCount, POINT* p0, POINT* p1);
   void RemoveSameStrokeEnds();
   bool InSameArea(POINT* pt0, POINT*pt1);
   void CreateStrokes();
   void WrapPoint (const POINT* ptInput, POINT* ptOutput);

protected:
   int m_nYCross[MAX_TRANVAS];
   int m_nXCross[MAX_TRANVAS];
   POINT m_ptStrokeEnds[MAX_STROKE_ENDS];
   UINT m_uValidEnds;
};

// GetIntersects:
// Returns the numbers of intersects from p0 to p1 to a interval width grid.
// p0 is the starting point, p1 is the ending point.
// interval is the interval of the grid.
// arrIntersects are the output array to record. n*interval-1 or n*interval. 
// nArrayLength is input. how many elements arrIntersects can contain.
// If p0/p1 itself is one intersect, they are not counted.
int GetIntersects(int p0, int p1, int interval, int* arrIntersects, int nArrayLength);

// Y2X:
// returns X value from given Y.
// The line is decided by p0 and p1
int Y2X (POINT* p0, POINT* p1, int y);

// X2Y:
// returns X value from given Y.
// The line is decided by p0 and p1
int X2Y (POINT* p0, POINT* p1, int x);

#endif /* __TROPHY_LOGO_EXECUTOR_H__ */
